var express = require('express');
var db = require('./db-config.js');
var users = require('./users.js');
var api = require('./footballAPI.js');
var game = require('./game.js');
var cron = require('./cron-job.js');
//var mondial = require('./mondial.js');

var app = express();
app.configure(function() {
    //app.use(express.logger('dev'));
    // show messages in the prompt
    app.use(express.bodyParser(/*{ keepExtensions: true, uploadDir: __dirname + '/uploads' }*/));
    //it will parse json request bodies (as well as others), and place the result in req.body:
});

app.use('/public', express.static(__dirname + '/public'));
app.use('/', express.static(__dirname + '/public'));
app.get('/login/:player/:password', oldUserlogin);
app.get('/signup/:player/:password', newUserSignup);
app.get('/getLevel/:level/:collection', getLevel);
//app.post('/placeLevelBet', placeBet);
app.get('/tournamentBets/:collection', getAllTournamentBets);
app.get('/getGroupStage/:groupName/:collection', getGroupStage);
app.get('/bettingPage/:name', setupBetPage);
app.get('/users/:collection', listUsers);
app.get('/newMappings/:level', getLevelMapping);
app.get('/getQualifiers/:groupName/:collection', getQualifiers);
app.get('/todaysMatches/:date', getTodayMatches);
app.get('/newQualifiersMapping/', getQualifiersMapping);
app.post('/submitKnockoutAndGroupBet/:level/:name', submitUserMatchesBet);
app.post('/submitQualifiersBet/:name', submitUserQualifiersBet);
app.get('/checkBetStatus/', getBetStatus);
app.get('/collectionSignup/:name/:collectionName/:collectionPass', newCollectionSignup);
app.get('/collectionLogin/:name/:collectionPass/:collectionName', oldCollectionLogin);
app.get('/collectionsFetch/', getAllCollections);
app.get('/usersOpenMatch/:match_id/:name/:level', openGame);
app.get('/usersWorld/', listWorldUsers);
app.get('/userRemoveCollection/:name', userRemoveCollection);
app.post('/submitTournBet/:name', setupTournamentBet);
app.get('/usersNameChange/:name/:oldName', changeUserName);
app.get('/usersProfile/:name', getPlayerProfile);
app.listen(process.env.VCAP_APP_PORT || 3000);

/***
 * Sends the list of users to the client side - names,points,champion team,next match bet
 * @return {array} Sorted array of {name:<name>, points:<points>, champion:<champion>, nextMatch:[match_id:<match_id> , score:<score>]}
 */
function listUsers(req, res) {
    var collectionName = req.params.collection;
    users.listAllUsers(collectionName, function(result) {
        // console.log('listing all users in - ' + collectionName);
        res.send(result);
    });
}

function changeUserName(req, res) {
    users.editProfile(req.params.name, req.params.oldName);
    res.send(true);
}

function getPlayerProfile(req, res) {
    users.userProfile(req.params.name, function(result) {
        if (result != null) {
            res.send(JSON.stringify(result));
        } else {
            console.log("app - Error getting profile for player- " + req.params.name);
            res.send(null);
        }

    });
}

/**
 * Attempts to remove this user's collection to null - sends true if success, false otherwise (should always be true..)
 */
function userRemoveCollection(req, res) {
    var name = req.params.name;
    users.removeCollectionFromUser(name);
    console.log(name + " has been removed from his collection");
    res.send(true);
}

/**
 * Sends to client ALL the users from ALL the collections
 */
function listWorldUsers(req, res) {
    users.listWorldUsers(function(result) {
        //   console.log('listing all users');
        res.send(result);
    });
}

function submitUserMatchesBet(req, res) {
    var level = parseInt(req.params.level);
    var name = req.params.name;
    var winner = null;
    for (var i = 0; i < req.body.length; i++) {
        var tempMatch = req.body[i];
        if (level != 0) {
            users.insertKnockoutMatchBet(4 - level, tempMatch.match_id, tempMatch.winner, tempMatch.score, name);

        } else {
            users.insertGroupMatchBet(null, tempMatch.match_id, tempMatch.score, name);
        }

    };
    res.send(true);
}

/**
 * Inserts the POST bet in to the user's DB
 * Called only in the group stage
 */
function submitUserQualifiersBet(req, res) {
    game.isBettingAllowed(function(betBoolean) {
        if (betBoolean) {
            var name = req.params.name;
            var qualBets = req.body;
            for (var i = 0; i < qualBets.length; i++) {
                var tempQual = qualBets[i];
                users.insertQualifiersBet(tempQual.groupName, [tempQual.rankedFirst.trim(), tempQual.rankedSecond.trim()], name);
            }
            res.send(true);
        } else {
            res.send(false);
        }
    });

}

/**
 * This user sends to the client all the games for this user
 * @return {match_id : <value> , home:<bool> , away:<bool>}
 */
function setupBetPage(req, res) {
    game.isBettingAllowed(function(betBoolean) {
        if (betBoolean) {

            var name = req.params.name;
            db.users.findOne({
                name : 'sudo'
            }, {
                betOpen : 1,
                betLevel : 1
            }, function(err, realBetLevel) {
                if (err || !realBetLevel) {
                    console.log("Error setting up the betting level");
                    res.send(null);
                } else {
                    //Get the current level (0-4)
                    var level = realBetLevel.betLevel;
                    users.getKnockoutLevelForUser(level, name, function(result) {
                        //console.log("Sending upcoming bets for - " + name);
                        res.send({
                            level : level,
                            result : result
                        });
                    });
                }
            });
        } else {
            res.send(null);
        }
    });

}

/**
 * Checks with Sudo what is the status on the betting page - true if open, false if closed
 */
function getBetStatus(req, res) {
    db.users.findOne({
        name : 'sudo'
    }, {
        betOpen : 1,
        betLevel : 1
    }, function(err, betStatus) {
        if (err || !betStatus) {
            console.log("app - Error finding bet status");
        } else {
            //Get the current level (0-4)

            res.send(JSON.stringify({
                betLevel : betStatus.betLevel,
                betOpen : betStatus.betOpen
            }));

        }
    });
}

/**
 * Sends the client - all the tournament bets for all users
 */
function getAllTournamentBets(req, res) {
    var collectionName = req.params.collection;
    users.getTournamentInfo(collectionName, function(result) {
        //console.log("app - Sending the client all the tournament bets");
        res.send(result);
    });
}

/**
 * Gets the upcoming matches and sends to client {match_id:<value>, date:<value>}
 */
function getTodayMatches(req, res) {
    var date = req.params.date;
    api.listMatchesByDate(date, function(result) {
        console.log("Sending matches for date - " + date);
        res.send(result);
    });
}

/***
 * Sends the list of users bets for this level to the client side
 * Don't forget to also send the SUDO results for this match!
 * @return in callback is an array of objects in the form of [{name:<name>,knockout:[{match_id:<value>, winner:<team_id>, score:[0,0]}]}]
 */
function getLevel(req, res) {
    var level = parseInt(req.params.level);
    var collectionName = req.params.collection;

    //Check if the level wanted is group stage
    if (level == 0) {
        //Here you need to know WHAT GROUP to bring

    } else {
        //Level wanted is a knockout level
        users.getKnockoutLevel(level, collectionName, function(result) {
            if (result == null) {
                console.log("Error getting users level - " + level);
                res.send(false);
            } else {
                console.log("Level " + level + " Found");
                res.send(JSON.stringify(result));
            }

        });
    }

}

/***
 * Sends the list of users bets for this group to the client side
 * Don't forget to also send the SUDO results for this match!
 * @return in callback is an array of objects in the form of [{name:<name>,group:[{match_id:<value>, score:[0,0]}]}]
 */
function getGroupStage(req, res) {
    var groupToGet = "World Cup, Group " + req.params.groupName;
    var collectionName = req.params.collection;
    users.getGroupLevel(groupToGet, collectionName, function(result) {
        if (result == null) {
            console.log("Error getting users group - " + groupToGet);
            res.send(false);
        } else {
            //console.log("Group " + groupToGet + " Found");
            res.send(result);
        }

    });

}

/***
 * Sends the list of users bets qualifiers for this group to the client side
 * Don't forget to also send the SUDO results for this match!
 * @return in callback is an array of objects in the form of [{name:<name>,rankedFirst:<value>,rankedSecond:<value>}]
 */
function getQualifiers(req, res) {
    var groupToGet = "World Cup, Group " + req.params.groupName;
    var collectionName = req.params.collection;
    users.getQualifiersBet(groupToGet, collectionName, function(result) {
        if (result == null) {
            console.log("Error getting users qualifiers - " + groupToGet);
            res.send(false);
        } else {
            //console.log("Qualifiers for " + groupToGet + " found");
            res.send(result);
        }

    });

}

/**
 * logs in the user and sends the info to the clientside
 * @param {Object} req
 * @param {Object} res
 */
function oldUserlogin(req, res) {
    var user = req.params.player;
    var password = req.params.password;
    users.login(user, password, function(result) {
        if (!result) {
            //No player was found
            console.log('User ' + user + ' not found');
            res.send(false);
        } else {
            //User was found
            console.log(user + ' has logged in');
            //When user is logged in - send the info
            res.send(true);
        }
    });
}

/**
 * Signs up this user - after checking he doesn't exist first!!
 */
function newUserSignup(req, res) {
    game.isBettingAllowed(function(betBoolean) {
        if (betBoolean) {
            var user = req.params.player;
            var password = req.params.password;
            users.userExists(user, function(result) {
                console.log(result);
                if (result) {
                    //User is new
                    console.log('Singing up ' + user);
                    users.signup(user, password);
                    res.send(true);
                } else {
                    console.log("app - User exists - can't sign up");
                    res.send(false);
                }
            });

        } else {
            //Can't log in user because BETTING IS FINISHED!!!
            console.log("app - Betting has ended - can't create a new user");
            res.send(false);

        }
    });
};

/**
 * Attempts to create a new collection sends true if yes, false if exists already
 * If successfull  puts the new collection in this user's collection:<value>
 */
function newCollectionSignup(req, res) {
    var name = req.params.name;
    var collectionPass = req.params.collectionPass;
    var collection = req.params.collectionName;
    users.collectionExists(collection, function(result) {
        if (result) {
            users.loginCollection(name, collection, collectionPass, function(isLogged) {
                //Check to see if the login was succesfull
                if (isLogged) {
                    //Append the new collection to Sudo's collections
                    db.users.update({
                        name : 'sudo'
                    }, {
                        $push : {
                            collections : {
                                name : collection,
                                password : collectionPass
                            }
                        }
                    });
                    res.send(true);
                } else {
                    res.send(false);
                }
            });

        }
    });
}

/**
 * Logs in the user, sends true if yes, false if no
 */
function oldCollectionLogin(req, res) {
    var name = req.params.name;
    var collectionPass = req.params.collectionPass;
    var collection = req.params.collectionName;
    users.loginCollection(name, collection, collectionPass, function(isLogged) {
        //Check to see if the login was succesfull
        if (isLogged) {
            res.send(true);
        } else {
            console.log("Could not log user in, either he is in a different collection, or he doesnt exist - " + name);
            res.send(false);
        }
    });
}

/**
 * Fetches from sudo all the collections
 */
function getAllCollections(req, res) {
    db.users.findOne({
        name : 'sudo'
    }, {
        collections : 1
    }, function(err, result) {
        if (err || !result) {
            //Bad
            res.send(null);
        } else {
            //Return all the collections
            res.send(result.collections);
        }
    });
}

// /**
// * Takes bet from clientside and places the bet -
// * TODO: Does it return something to the user? what?
// * @param {Object} req
// * @param {Object} res
// */
// function placeBet(req, res) {
// var obj = req.body;
// var playerName = obj.name;
// var numOfMatches = obj.matches.length;
// //TODO: Validate the bets before placing them users.validateBeforeBet --> users.placeKnockoutBet
//
// }

/**
 * Checks if the user has enough points to open the game , and that one of the teams is open - if not - the user can not open
 * @param level from 1-4 , 1 being the final
 * @return false if the game has been opened, false if not
 */
function openGame(req, res) {
    game.isBettingAllowed(function(betBoolean) {

        if (betBoolean) {

            var playerName = req.params.name;
            var gameToOpen = req.params.match_id;
            var levelOfGame = req.params.level;
            users.isGameOpenable(playerName, gameToOpen, game.rules[levelOfGame], function(result) {
                if (result) {
                    //User has opened the game
                    //Deduct points for this user
                    users.takePoints(game.rules[levelOfGame], playerName);
                    console.log("Opened game for - " + playerName);
                    res.send(true);
                } else {
                    //User can NOT open this game
                    console.log("Can not open game for - " + playerName);
                    res.send(false);
                }
            });
        } else {
            //Betting not allowed
            res.send(false);
        }

    });

}

/**
 * Gets the profile for this user - including games that are closed/open etc
 * @param {Object} req
 * @param {Object} res
 */
function playerProfile(req, res) {
    var user = req.params.player;
    users.getUserTournamentInfo(user, function(result) {
        if (result == null) {
            //User was not found
            console.log("User does't exist");
            res.send(false);
        } else {
            //User found
            console.log('User has been found');
            res.send(result);
        }
    });
}

/**
 * Lets the user edit his profile (for example tournament bets before the group starts)
 * and his name, picture etc.
 * @param {Object} req
 * @param {Object} res
 */
function editProfile(req, res) {
}

/**
 * Sets up the next bet when client entered the betting page
 * Finds Which bet is next, sends the teams and games that can be bet on - including the rules for this betting stage
 * and time to place next bet - this part also needs to see if he can bet on this game!
 * @param {Object} req
 * @param {Object} res
 * @return
 */
function nextKnockoutBet(req, res) {
    var bettingLevel = req.params.level;
    var player = req.params.name;
    //Sudo SHOULD hold all the real winning teams - OR I can go to the API.. which?
    users.getKnockoutLevelForUser(bettingLevel, player, function(result) {
        console.log(result);
    });

}

/**
 * Sends the client the mapping of the matches to teams to put in client Localstorage
 * @param level wanted
 * @return [{match_id:<value> , teams:[<value>,<value>]}]
 */
function getLevelMapping(req, res) {
    var level = req.params.level;
    //Now holds the array
    api.getMappingByLevel(level, function(result) {
        if (result == null) {
            console.log("Error getting new mapping for level - " + level);
            //Can NOT happen!
            res.send(false);
        } else {
            res.send(result);
        }

    });
}

/**
 * Sends the mapping of qualifiers, should happen once for each user.
 * @return is an array: {groupName:<value> , teams:[4]}
 */
var allQualifiersMap = null;
function getQualifiersMapping(req, res) {
    if (allQualifiersMap == null) {
        api.getAllQualifiersMapping(function(result) {
            if (result == null) {
                console.log("app - error getting the qualifiers mapping");
                res.send(null);
            } else {
                allQualifiersMap = result;
                res.send(result);
            }
        });
    } else {
        res.send(allQualifiersMap);
    }

}

/**
 * Sets up the tournament bets - even though this is built in
 */
function setupTournamentBet(req, res) {
    var player = req.params.name;
    var choices = req.body;
    users.insertTournamentBet(choices, player);
    res.send(true);
}

/** TEST AREA **/
// db.users.remove();
//users.signup("sudo");
// users.signup("Foo Bar");
// users.signup("Tomer Honigman");
// users.insertGroupMatchBet(null, "03702fc0-6f31-4b66-aeef-ffff98cc033b", [2, 1], "Tomer Honigman");
// users.insertKnockoutMatchBet(null, "ae54d136-d119-429f-9a02-79854d68510b", "Spain", [0, 2], "Tomer Honigman");
// users.insertQualifiersBet("World Cup, Group D", ["Israel", "Yugoslavia"], "Tomer Honigman");
// users.insertQualifiersBet("World Cup, Group B", ["France", "Algeria"], "Tomer Honigman");
// users.insertKnockoutMatchBet(null, "ae54d136-d119-429f-9a02-79854d68510b", "England", [0, 5], "Foo Bar");
// users.insertQualifiersBet("World Cup, Group A", ["Russia", "China"], "Foo Bar");
// users.insertGroupMatchBet(null, "03702fc0-6f31-4b66-aeef-ffff98cc033b", [2, 1], "Foo Bar");
// users.insertTournamentBet({
// mvp : "Inzaghi",
// champion : "Spain",
// kingOfGoals : "Ronaldo",
// kingOfAssists : "Mario Gotze",
// leastGoalsConceded : "Israel",
// mostGoalsScored : "Brazil"
// }, "Ore Poran");

// users.getGroupMatchBet("03702fc0-6f31-4b66-aeef-ffff98cc033b", "sudo", function(result) {
// console.log(JSON.stringify(result));
// });
// users.getGroupLevel("World Cup, Group B", function(result) {
// console.log(JSON.stringify(result));
// });

// users.getKnockoutLevel(4, function(result) {
// console.log(JSON.stringify(result));
// });

//
// users.getKnockoutMatchBet("ae54d136-d119-429f-9a02-79854d68510b", "Yahav Winkler", function(result) {
// console.log(JSON.stringify(result));
// });

// users.getKnockoutLevelForUser(0,"Ore Poran",function(result){
// console.log(result);
// });

//THIS IS WHERE I INSERT SCORES IN TO SUDO (SHOULD BE DONE WITH game.UPDATE BY CRON)

// users.insertQualifiersBet("World Cup, Group C", ["Ivory Coast", "Japan"], 'sudo');
// users.insertGroupMatchBet(null, "1b7f9a66-1ac3-426d-b2b1-410b0103d34b", [2, 1], 'sudo');
// //
// game.gameOver("Group", 0, "1b7f9a66-1ac3-426d-b2b1-410b0103d34b", null);
// // game.gameOver("Knockout", 2, "ae54d136-d119-429f-9a02-79854d68510b", null);
// game.gameOver("Qualifier", 0, null, "World Cup, Group C");
// users.lockKnockoutGame("ae54d136-d119-429f-9a02-79854d68510b", {
// home : true,
// id : "22653ed5-0b2c-4e30-b10c-c6d51619b52b"
// });
// users.lockGroupGames("World Cup, Group C", {
// firstMatch : "2339574a-5064-4384-9ff5-5f76dca518a8",
// secondMatch : "9ccf78a3-5c63-40d3-b618-007952b52738"
// });
// users.validateBeforeBet("Ore Poran", "9ccf78a3-5c63-40d3-b618-007952b52738", function(bool) {
// console.log(bool);
// });

// users.insertKnockoutMatchBet(null, "9ccf78a3-5c63-40d3-b618-007952b52738", "Israel", [2, 4], "Ore Poran");
// users.insertKnockoutMatchBet(null, "9ccf78a3-5c63-40d3-b618-007952b52738", "Spain", [6, 1], "Ore Poran");

// users.listAllUsers(function(result) {
// console.log(result);
// });
//
// users.getKnockoutLevelForUser(4, "Ore Poran", function(result) {
// console.log(result);
// });

// users.getQualifiersBet("World Cup, Group A",function(result){
// console.log(result);
// });
console.log(new Date());

//game.updateGroupMatch([1, 3], "dc7425cf-73b1-411e-82dd-1b79c0b003f1");
// game.sudoAdvanceGroupTeams("Colombia", "Greece", function(result) {
    // users.lockGroupGames("World Cup, Group C", result);
    // game.sudoAdvanceGroupTeams("Costa Rica", "Uruguay", function(resultSecond) {
        // users.lockGroupGames("World Cup, Group D", resultSecond);
        // game.sudoAdvanceGroupTeams("France", "Switzerland", function(resultThird) {
            // users.lockGroupGames("World Cup, Group E", resultThird);
            // game.sudoAdvanceGroupTeams("Argentina", "Nigeria", function(resultFour) {
                // users.lockGroupGames("World Cup, Group F", resultFour);
// 
            // });
        // });
    // });
// });
//game.updateGroupLevel("World Cup, Group C");
// setTimeout(function() {
// game.updateGroupLevel("World Cup, Group D");
// }, 1000);

//game.updateGroupLevel("World Cup, Group F");

// setTimeout(function() {
// game.updateGroupLevel("World Cup, Group F");
// }, 10000);

api.getSchedule();
